<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="author" content="Klzgrad 
                               '+''+e+''+'');
                               // -->
                               &#x6b;&#x69;&#122;&#100;&#x69;&#118;&#32;&#x61;&#116;&#32;&#x67;&#x6d;&#x61;&#x69;&#108;&#32;&#100;&#x6f;&#116;&#32;&#x63;&#x6f;&#x6d;" />
  <title>West-chamber HOWTO</title>
  <style type="text/css">
  body {
      margin: auto;
      padding-right: 1em;
      padding-left: 1em;
      max-width: 44em; 
      border-left: 1px solid black;
      border-right: 1px solid black;
      color: black;
      font-family: Verdana, sans-serif;
      font-size: 100%;
      line-height: 140%;
      color: #333; 
  }
  pre {
      border: 1px dotted gray;
      background-color: #ececec;
      color: #1111111;
      padding: 0.5em;
  }
  code {
      font-family: monospace;
  }
  h1 a, h2 a, h3 a, h4 a, h5 a { 
      text-decoration: none;
      color: #7a5ada; 
  }
  h1, h2, h3, h4, h5 { font-family: verdana;
                       font-weight: bold;
                       border-bottom: 1px dotted black;
                       color: #7a5ada; }
  h1 {
          font-size: 130%;
  }
  
  h2 {
          font-size: 110%;
  }
  
  h3 {
          font-size: 95%;
  }
  
  h4 {
          font-size: 90%;
          font-style: italic;
  }
  
  h5 {
          font-size: 90%;
          font-style: italic;
  }
  
  h1.title {
          font-size: 200%;
          font-weight: bold;
          padding-top: 0.2em;
          padding-bottom: 0.2em;
          text-align: left;
          border: none;
  }
  
  dt code {
          font-weight: bold;
  }
  dd p {
          margin-top: 0;
  }
  
  #footer {
          padding-top: 1em;
          font-size: 70%;
          color: gray;
          text-align: center;
  }
  </style>
</head>
<body>
<h1 class="title">West-chamber HOWTO</h1>
<div id="TOC">
<ul>
<li><a href="#&#36215;&#27493;"><span class="toc-section-number">1</span> 起步</a></li>
<li><a href="#zhang-&#23458;&#25143;&#31471;tcp&#36830;&#25509;&#28151;&#28102;"><span class="toc-section-number">2</span> ZHANG: 客户端TCP连接混淆</a></li>
<li><a href="#&#35760;&#24405;gfw&#20135;&#29983;&#30340;&#20266;&#21253;"><span class="toc-section-number">3</span> 记录GFW产生的伪包</a></li>
<li><a href="#dns&#20813;&#27745;&#26579;&#21163;&#25345;"><span class="toc-section-number">4</span> DNS免污染、劫持</a></li>
<li><a href="#cui-&#26381;&#21153;&#31471;tcp&#36830;&#25509;&#28151;&#28102;"><span class="toc-section-number">5</span> CUI: 服务端TCP连接混淆</a></li>
<li><a href="#&#20351;&#29992;ipset&#38480;&#21046;&#24037;&#20316;&#33539;&#22260;"><span class="toc-section-number">6</span> 使用ipset限制工作范围</a></li>
<li><a href="#&#29305;&#24615;"><span class="toc-section-number">7</span> 特性</a></li>
<li><a href="#&#35786;&#26029;&#25925;&#38556;"><span class="toc-section-number">8</span> 诊断故障</a></li>
</ul>
</div>
<h1 id="&#36215;&#27493;"><a href="#TOC"><span class="header-section-number">1</span> 起步</a></h1>
<p>在安装完成之后，可以尝试：</p>
<pre><code># iptables -A INPUT -p tcp --sport 80 --tcp-flags FIN,SYN,RST,ACK SYN,ACK\
                    -m state --state ESTABLISHED -j ZHANG
# iptables -A INPUT -p tcp --sport 80 -m state --state ESTABLISHED -m gfw\
                    -j LOG --log-level info --log-prefix &quot;gfw: &quot;
# iptables -A INPUT -p udp --sport 53 -m state --state ESTABLISHED -m gfw\
                    -j DROP
# mv /etc/resolv.conf /etc/resolv.conf.old
# echo nameserver 8.8.8.8 &gt; /etc/resolv.conf
</code></pre>
<p>然后可以开始测试，比如Youtube。下面详细解释含义。</p>
<h1 id="zhang-&#23458;&#25143;&#31471;tcp&#36830;&#25509;&#28151;&#28102;"><a href="#TOC"><span class="header-section-number">2</span> ZHANG: 客户端TCP连接混淆</a></h1>
<pre><code># iptables -A INPUT \
    -p tcp --sport 80 --tcp-flags FIN,SYN,RST,ACK SYN,ACK \
    -m state --state ESTABLISHED \
    -m set --match-set NOCLIP src \
    -j ZHANG \
    -m comment --comment &quot;client-side connection obfuscation&quot;
</code></pre>
<p>这条规则意味着当在TCP/80端口收到一个SYN/ACK包，并且这个包对应了一个活动的TCP连 接，并且源地址在NOCLIP定义的地址段中，就执行ZHANG动作，发出特制的包混淆连接， 导致GFW认为连接已经结束，但是实际上连接继续，从而避免关键词检测。</p>
<p>但是对于一些不遵守RFC的目标主机或者防火墙，这可能导致正常不含关键词的连接被对 方终止或者忽略。这也就是使用ipset限制ZHANG的作用范围的动机。在极少的情况下会出 现其他特殊的现象，因此我们需要采取下面的措施。</p>
<h1 id="&#35760;&#24405;gfw&#20135;&#29983;&#30340;&#20266;&#21253;"><a href="#TOC"><span class="header-section-number">3</span> 记录GFW产生的伪包</a></h1>
<pre><code># iptables -A INPUT \
    -p tcp --sport 80 \
    -m state --state ESTABLISHED \
    -m gfw \
    -j LOG --log-level info --log-prefix &quot;gfw: &quot; \
    -m comment --comment &quot;log gfw tcp resets&quot;
</code></pre>
<p><code>-m gfw</code>的作用就是根据包的字段监测GFW的报文指纹。当浏览器中看见连接重置的时候， 去检查syslog就可以知道是否是GFW所为。</p>
<h1 id="dns&#20813;&#27745;&#26579;&#21163;&#25345;"><a href="#TOC"><span class="header-section-number">4</span> DNS免污染、劫持</a></h1>
<pre><code># iptables -A INPUT \
    -p udp --sport 53 \
    -m state --state ESTABLISHED \
    -m gfw \
    -j DROP \
    -m comment --comment &quot;drop gfw dns hijacks&quot;
</code></pre>
<p><code>-m gfw</code>同样可以匹配GFW发出的DNS劫持包，并针对性地采取丢弃的措施。将nameserver 设置（resolv.conf或者dhclient.conf中的prepend domain-name-servers以永久保存此 优先设置）为一个未受污染的服务器，比如8.8.8.8，然后开启此条规则，便可获得正确 的解析结果。</p>
<h1 id="cui-&#26381;&#21153;&#31471;tcp&#36830;&#25509;&#28151;&#28102;"><a href="#TOC"><span class="header-section-number">5</span> CUI: 服务端TCP连接混淆</a></h1>
<pre><code># iptables -A INPUT \
    -p tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN \
    -m state --state NEW \
    -j CUI \
    -m comment --comment &quot;server-side connection obfuscation&quot;
</code></pre>
<p>原理与ZHANG类似，只是方向相反。</p>
<h1 id="&#20351;&#29992;ipset&#38480;&#21046;&#24037;&#20316;&#33539;&#22260;"><a href="#TOC"><span class="header-section-number">6</span> 使用ipset限制工作范围</a></h1>
<p><em>注意</em>：ipset的版本应该大于4.2，否则hash表扩大的时候某种参数设置可能会导致 kernel oops。在0.0.1以后的版本中已经移除了自带的ipset，请使用发行版提供的 ipset。</p>
<p>ipset可以高效地定义一组ip地址，使得一条iptables规则就可以匹配处理这些地址。在 <code>examples</code>目录中提供了Google的地址段的ipset定义，你也可以自己定义其他的地址段。</p>
<p>例如：定义Google的地址段：</p>
<pre><code># ipset -R
-N YOUTUBE nethash --hashsize 50 --probes 1
-A YOUTUBE 64.15.112.0/20
-A YOUTUBE 82.129.37.0/24
-A YOUTUBE 208.65.152.0/22
-A YOUTUBE 208.117.224.0/19
-A YOUTUBE 213.146.171.0/24
COMMIT
^D
</code></pre>
<p>如果<code>--hashsize</code>不够大，ipset会自动调整尺寸并记录到syslog。如果尺寸扩大次数太 多则考虑增大probes值。<code>--probes</code>值越低匹配性能越好，但是会导致hash表尺寸较大； 反之如果probes值较大，hash表尺寸会比较小，但是匹配性能低一些。你可以根据情况调 整到满意的数值。</p>
<p>你也可使用<code>examples/ipsets</code>目录中提供的文件进行设置：</p>
<pre><code># cd examples
# ipset -R &lt; YOUTUBE
# ipset -R &lt; GOOGLE
# ipset -R &lt; NOCLIP
</code></pre>
<p>在定义完几个网段之后你可以把这些网段一起组成一个列表：</p>
<pre><code># ipset -R
-N NOCLIP setlist --size 4
-A NOCLIP GOOGLE
-A NOCLIP YOUTUBE
COMMIT
^D
</code></pre>
<p>然后在iptables规则中直接使用set匹配即可：</p>
<pre><code>-m set --match-set NOCLIP src
</code></pre>
<h1 id="&#29305;&#24615;"><a href="#TOC"><span class="header-section-number">7</span> 特性</a></h1>
<p>对于无法采取IP地址封锁的目标，这种方法特别有效。一个最直接的例子就是Youtube以 及其他所有Google产品，可以通过这种方式在ipv4线路上不经过代理直连。初期测试中， Youtube使用非常流畅。</p>
<p>需要注意的是，ZHANG和CUI是“最终目标”，它们会直接ACCEPT送给它们的包，因此对于这 些包，之后的规则都不会起作用。所以某些情况下你应该将以ZHANG或CUI为目标的规则放 在最后、其他过滤规则的后面。</p>
<h1 id="&#35786;&#26029;&#25925;&#38556;"><a href="#TOC"><span class="header-section-number">8</span> 诊断故障</a></h1>
<p>当浏览器仍然显示连接重置的时候，检查syslog看是否是GFW所为。</p>
<p>也可以用tcpdump保存流量，当问题发生时可以用wireshark回溯查找原因。</p>
<pre><code>tcpdump -Kpq -C2 -W10 -ieth0 -s0 -wcap port 80
</code></pre>
<p>当浏览器工作不正常时，输入<code>fg</code>然后<code>^C</code>结束程序，打开最新的一个dump。稍微解释一 下参数含义：<code>-K</code>不检查TCP检验和，<code>-p</code>不使用混杂模式，<code>-q</code>安静，<code>-C2</code>每2000000 字节换一个文件保存，<code>-W10</code>最多十个文件循环使用，<code>-ieth0</code>使用eth0，<code>-s0</code>捕获整 个包，<code>-wcap</code>文件名为“capXX”。也可以自行调整。</p>
</body>
</html>
